export const isNaN = Number.isNaN || Window.isNaN

export function isNumber(value) {
    return typeof value === 'number' && !isNaN(value)
}

export function isObject(value) {
    return typeof value === 'object' && value !== null
}

export function isFunction(value) {
    return typeof value === 'function'
}

export function forEach(data, callback) {
    if (data && isFunction(callback)) {
        if (Array.isArray(data) || isNumber(data.length)) {
            const {length} = data
            for (let i = 0; i < length; i++) {
                if (callback.call(data, data[i], i, data) === false) {
                    break
                }
            }
        } else if (isObject(data)) {
            Object.keys(data).forEach((key) => {
                callback.call(data, data[key], key, data)
            })
        }
    }
}

export function addListener(element, type, listener, options = {}) {
    element.addEventListener(type, listener, options);
}

export function removeListener(element, type, listener, options = {}) {
    console.log('utils', 'removeListener');
    element.removeEventListener(type, listener, options)
}

export function dispatchEvent(element, type, data) {
    console.log('utils', 'dispatchEvent');
    let event;
    if (isFunction(Event) && isFunction(CustomEvent)) {
        event = new CustomEvent(type, {
            detail: data,
            bubbles: true,
            cancelable: true
        })
    } else {
        event = document.createEvent('CustomEvent')
        event.initCustomEvent(type, true, true, data)
    }
    return element.dispatchEvent(event)
}

export function addClass(element, value) {
    if (element.classList) {
        element.classList.add(value)
        return;
    }
    const className = element.className.trim();
    if (!className) {
        element.className = value;
    } else {
        element.className = `${className} ${value}`;
    }
}

export function removeClass(element, value) {
    if (element.classList) {
        element.classList.remove(value)
        return
    }
    if (element.className.indexOf(value) >= 0) {
        element.className = element.className.replace(value, '')
    }
}

export function toggleClass(element, value, added) {
    if (!value) return
    if (isNumber(element.length)) {
        forEach(element, (elem) => {
            toggleClass(elem, value, added)
        })
        return;
    }
    if (added) {
        addClass(element, value)
    } else {
        removeClass(element, value)
    }
}

const REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g;

// 字符串从驼峰式（camelCase）转为短横线式（kebab-case）
export function hyphenate(value) {
    return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase();
}

export function getData(element, name) {
    if (element.dataset) {
        return element.dataset[name];
    }

    return element.getAttribute(`data-${hyphenate(name)}`);
}

export function setData(element, name, data) {
    if (element.dataset) {
        element.dataset[name] = data
    } else {
        element.setAttribute(`data-${hyphenate(name)}`, data)
    }
}

export function getImageNaturalSizes(image, callback) {
    const newImage = document.createElement('img')
    if (image.naturalWidth) {
        callback(image.naturalWidth, image.naturalHeight)
        return newImage;
    }
    const body = document.body || document.documentElement
    newImage.onload = () => {
        callback(newImage.width, newImage.height)
    }
    newImage.src = image.src
    newImage.style.cssText = (`
      top:0;left:0;opacity:0;
      z-index:-1;position:absolute;
      max-height:none!important;
      max-width:none!important;
      min-height:0!important;
      min-width:0!important;
    `)
    body.appendChild(newImage)

    return newImage
}

export function getTransforms({rotate, scaleX, scaleY, translateX, translateY}) {
    const values = []

    if (isNumber(translateX) && translateX !== 0) {
        values.push(`translateX(${translateX}px)`)
    }
    if (isNumber(translateY) && translateY !== 0) {
        values.push(`translateY(${translateY}px)`)
    }
    if (isNumber(rotate) && rotate !== 0) {
        values.push(`rotate(${rotate}deg`)
    }
    if (isNumber(scaleX) && scaleX !== 0) {
        values.push(`scaleX(${scaleX})`)
    }
    if (isNumber(scaleY) && scaleY !== 0) {
        values.push(`scaleY(${scaleY})`)
    }
    const transform = values.length ? values.join(' ') : 'none'
    return {WebkitTransform: transform, msTransform: transform, transform}
}

const REGEXP_SUFFIX = /^(?:width|height|left|top|marginLeft|marginTop)$/;

export function setStyle(element, styles) {
    const {style} = element;
    forEach(styles, (value, property) => {
        if (REGEXP_SUFFIX.test(property) && isNumber(value)) {
            value += 'px';
        }
        style[property] = value;
    });
}
